package handlers

import (
	"encoding/json"
	"fmt"
	"gitee.com/Cookie_XiaoD/go-filestore-server/db"
	"gitee.com/Cookie_XiaoD/go-filestore-server/util"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"time"
)

//UserSignup 用户注册
func UserSignup(w http.ResponseWriter, r *http.Request) {
	//get请求返回注册页面
	if r.Method == http.MethodGet {
		SendStaticHTML("../../static/view/signup.html", w, r)
		return
	}

	//post进行注册
	bodyBytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Printf("获取Body错误：%v", err.Error())
		SendJsonResp(w, BuildArgsErrResp())
		return
	}
	req := &signupReq{}
	err = json.Unmarshal(bodyBytes, req)
	if err != nil {
		log.Printf("序列化body错误：%v ,json:%v", err.Error(), string(bodyBytes))
		SendServerErrResp(w)
		return
	}

	encode_pwd := util.Sha1([]byte(req.UserPwd + util.Enc_salt))
	suc, err := db.UserSignup(req.UserName, encode_pwd)
	if !suc {
		SendServerErrResp(w)
		return
	}
	SendJsonResp(w, BuildSuccessResp(nil))

}

func UserSignIn(w http.ResponseWriter, r *http.Request) {
	if r.Method == http.MethodGet {
		SendStaticHTML("../../static/view/signin.html", w, r)
		return
	}

	//post进行登录
	bodyBytes, err := ioutil.ReadAll(r.Body)
	if err != nil {
		log.Printf("获取Body错误：%v", err.Error())
		SendJsonResp(w, BuildArgsErrResp())
		return
	}
	req := &signinReq{}
	err = json.Unmarshal(bodyBytes, req)
	if err != nil {
		log.Printf("序列化body错误：%v ,json:%v", err.Error(), string(bodyBytes))
		SendServerErrResp(w)
		return
	}
	//用户登录流程
	//1.判断用户是否存在
	encode_pwd := util.Sha1([]byte(req.UserPwd + util.Enc_salt))
	suc, err := db.UserSignIn(req.UserName, encode_pwd)
	if !suc {
		SendServerErrResp(w)
		return
	}

	//2.如果用户存在 则创建或更新token
	token := getToken(req.UserName)
	if res := db.InsertOrUpdateUserToken(req.UserName, token); !res {
		SendServerErrResp(w)
		return
	}

	//3.返回token
	data := struct {
		Location string
		UserName string
		Token    string
	}{
		Location: "/views/home.html",
		UserName: req.UserName,
		Token:    token,
	}
	SendJsonResp(w, BuildSuccessResp(data))
}

//getToken 获取用户token
func getToken(userName string) string {
	//16进制8位足以保证到2106-02-07 14:28:15
	//token为40位字符 (userName+时间戳16位格式+token_salt)+时间戳16位格式后8位
	ts := fmt.Sprintf("%x", time.Now().Unix())
	tokenPrefix := util.MD5([]byte(userName + ts + "token_salt_1"))
	return tokenPrefix + ts[:8]
}

// IsTokenValid : token是否有效
func IsTokenValid(token string) bool {
	if len(token) != 40 {
		return false
	}
	// 1.判断token的时效性，是否过期
	//获取token的后8位，是过期时间
	timestampHex := token[32:]
	//log.Println("时间戳："+timestampHex)
	ts, err := strconv.ParseInt(timestampHex, 16, 64)
	if err != nil {
		return false
	}
	tokenTime := time.Unix(ts, 0)
	//log.Println("token的时间:"+tokenTime.Format("2006-01-02	15:04:05"))

	//过期时间24小时 TODO：目前写死过期时间
	log.Println(time.Now().Sub(tokenTime).Hours())
	if time.Now().Sub(tokenTime).Hours() > 24 {
		return false
	}

	log.Println("token未过期，检查db是否存在")
	// 2.若未过期 则从数据库表tbl_user_token查询对应的token信息 是否存在
	tokenPass := db.CheckUserTokenExists(token)

	return tokenPass
}

//UserInfo 用户信息接口
func UserInfo(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	username := r.Form.Get("username")
	if username == "" {
		SendJsonResp(w, BuildArgsErrResp())
		return
	}
	log.Printf("请求用户信息：%v", username)
	userInfo, err := db.GetUserInfo(username)
	if err != nil {
		SendServerErrResp(w)
		return
	}
	SendJsonResp(w, BuildSuccessResp(userInfo))

}

func UserHome(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		return
	}
	SendStaticHTML("../../static/view/home.html", w, r)
}
